package com.yklab.library.http;

import android.text.TextUtils;

import com.yklab.library.encrypt.AESUtils;
import com.yklab.library.json.JSONUtil;
import com.yklab.library.log.LogUtil;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
import okhttp3.ResponseBody;
import okhttp3.internal.http.RealResponseBody;
import okio.Buffer;
import okio.BufferedSource;
import okio.ForwardingSource;
import okio.Okio;
import okio.Source;

/**
 * 请求工具类
 * Created by yu on 2016/5/23.
 */
public class JCHttpManagerUtils {
    private String TAG = JCHttpManagerUtils.class.getSimpleName();

    public static int HTTP_SUCCESS = 1;
    public static int HTTP_FAILURE = 2;
    public static final MediaType MEDIA_TYPE_MARKDOWN = MediaType.parse("text/x-markdown; charset=utf-8");
    public static final MediaType MEDIA_TYPE_PNG = MediaType.parse("image/jpeg");
    public static final MediaType MEDIA_TYPE_JSON = MediaType.parse("application/json; charset=utf-8");
    public static final MediaType MEDIA_FORM_DATA = MediaType.parse("multipart/form-data; charset=utf-8");

    private OkHttpClient client = new OkHttpClient();

    public JCHttpManagerUtils() {
        initOKHttpClient();
    }

    /**
     * @return
     */
    public void initOKHttpClient() {
        int cacheSize = 10 * 1024 * 1024;
        OkHttpClient.Builder builder = new OkHttpClient.Builder()
                .connectTimeout(10, TimeUnit.SECONDS)
                .writeTimeout(10, TimeUnit.SECONDS)
                .readTimeout(10, TimeUnit.SECONDS);
//                .cache(new Cache(sdcache.getAbsoluteFile(), cacheSize));
        client = builder.build();
    }

    //get
    public void get(String httpUrl, Map<String, Object> params, Callback callback) {
        try {
            Map<String, Object> encryptParam = null;
            if (params != null && params.size() > 0) {
                LogUtil.i("请求参数", JSONUtil.toJSON(params));
                String strParam = AESUtils.Encrypt(JSONUtil.toJSON(params));
                encryptParam = new HashMap<>();
                encryptParam.put("enerypt", strParam);
            }
            LogUtil.i("请求的Url", createUrlFromParams(httpUrl, encryptParam));
            Request request = new Request.Builder()
                    .url(createUrlFromParams(httpUrl, encryptParam))
                    .get()
                    .build();
            Call call = client.newCall(request);
            call.enqueue(callback);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


    /**
     * 是否加密
     * isEncrypt true：加密, false：不加密
     *
     * @param httpUrl
     * @param params
     * @param callback
     */
    //get
    public void get(String httpUrl, Map<String, Object> params, Callback callback, boolean isEncrypt) {
        try {
            if (isEncrypt) {
                Map<String, Object> encryptParam = null;
                if (params != null && params.size() > 0) {
                    String strParam = AESUtils.Encrypt(JSONUtil.toJSON(params));
                    encryptParam = new HashMap<>();
                    encryptParam.put("enerypt", strParam);
                    LogUtil.i("get请求参数", encryptParam.toString());
                    params = encryptParam;
                }
            }
            Request request = new Request.Builder()
                    .url(createUrlFromParams(httpUrl, params))
                    .get()
                    .build();
            Call call = client.newCall(request);
            call.enqueue(callback);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * describe:不加密请求
     * author:czhang
     * date:2017/6/11 20:09
     */
    public void getNoEncrypt(String httpUrl, Map<String, Object> params, Callback callback) {
        try {
            Request request = new Request.Builder()
                    .url(createUrlFromParams(httpUrl, params))
                    .get()
                    .build();
            Call call = client.newCall(request);
            call.enqueue(callback);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * describe:请求特殊url非公司Url接口
     * author:yukang
     * date:2018/1/22
     */
    public void getSpecialUrl(String httpUrl, Map<String, Object> params, Callback callback) {
        try {
            Request request = new Request.Builder()
                    .url(createUrlFromParams(httpUrl, params))
                    .get()
                    .build();
            Call call = client.newCall(request);
            call.enqueue(callback);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 描述：无加密请求，请求参数json类型，新版app使用
     * date：2017.12.27
     *
     * @param httpUrl
     * @param key
     * @param value
     * @param callback
     */
    public void getNoEncrypt(String httpUrl, String key, Object value, Callback callback) {
        try {
            Request request = new Request.Builder()
                    .url(createUrlFromParams(httpUrl, key, value))
                    .get()
                    .build();
            Call call = client.newCall(request);
            call.enqueue(callback);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


    //post
    public void post(String httpUrl, RequestBody requestBody, Callback callback) {
        try {
            Request request = new Request.Builder()
                    .url(httpUrl)//完整的api路径
                    .post(requestBody)
                    .build();
            Call call = client.newCall(request);
            call.enqueue(callback);
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

//
//    /**
//     * 上传单个文件
//     */
//    public void uploadSingleFile(String httpUrl, String filepath, String fileType, Callback callback) {
//        File file = new File(filepath);
//
//        LogUtil.i("aaaa", "-----type--" + MimeUtils.getContentType(fileType)
//                + "---USERID:" + SharePreferencesUtils.getInstance().getValueByKey(YSConstant.SP_USERID));
//        Request request = new Request.Builder()
//                .url(httpUrl)
//                .addHeader("Content-Type", MimeUtils.getContentType(fileType))
//                .addHeader("x-oss-meta-author", "65439340511236096")
//                .put(RequestBody.create(MediaType.parse(MimeUtils.getContentType(fileType)), file))
//                .build();
//
//        client.newCall(request).enqueue(callback);
//    }
//
//
//    /**
//     * 下载文件
//     */
//    public void downLoadFile(String httpUrl, final String savePath, Callback callback) {
//        Request request = new Request.Builder().url(httpUrl)
//                .addHeader("userToken", SharePreferencesUtils.getInstance().getUserToken())
//                .build();
//        client.newCall(request).enqueue(callback);
//    }
//
//    /**
//     * 上传Multipart文件
//     */
//    public void uploadMultipartBody(String httpUrl, RequestBody requestBody, Callback callback) {
//        Request request = new Request.Builder()
//                .header("userToken", "Client-ID " + "...")
//                .addHeader("userToken", SharePreferencesUtils.getInstance().getUserToken())
//                .url(httpUrl)
//                .post(requestBody)
//                .build();
//
//        client.newCall(request).enqueue(callback);
//    }

    /**
     * 描述：新版app使用
     *
     * @param url
     * @return
     */
    private String createUrlFromParams(String url, String key, Object value) {
        if (value == null || TextUtils.isEmpty(key)) {
            return url;
        }
        StringBuilder sb = new StringBuilder();
        sb.append(url);
        if (url.indexOf("?") <= 0) {
            sb.append("?");
        }
        try {
            //String urlValue = URLEncoder.encode(JSONUtil.toJSON(value), "UTF-8");
            String urlValue = JSONUtil.toJSON(value);
            sb.append(key).append("=").append(urlValue);
            return sb.toString();
        } catch (Exception e) {
            LogUtil.e("error", "param_error:" + e.getMessage());
        }
        return url;

    }


    public static String createUrlFromParams(String url, Map<String, Object> params) {
        if (params == null || params.isEmpty()) {
            return url;
        }
        try {
            StringBuilder sb = new StringBuilder();
            sb.append(url);
            if (url.indexOf('&') > 0 || url.indexOf('?') > 0) {
                sb.append("&");
            } else {
                sb.append("?");
            }
            for (Map.Entry<String, Object> urlParams : params.entrySet()) {
                Object value = urlParams.getValue();
                String urlValue = URLEncoder.encode(String.valueOf(value), "UTF-8");
                sb.append(urlParams.getKey()).append("=").append(urlValue).append("&");
//                List<Object> urlValues = urlParams.getValue();
//                for (Object value : urlValues) {
//                    String urlValue = URLEncoder.encode(String.valueOf(value), "UTF-8");
//                    sb.append(urlParams.getKey()).append("=").append(urlValue).append("&");
//                }
            }
            sb.deleteCharAt(sb.length() - 1);

            LogUtil.i("网路请求", "___req_params:" + sb.toString());
            return sb.toString();
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return url;
    }


    public String getFileUploadUrl(String httpUrl, Map<String, Object> params) {
        String newUrl = "";
        Request request = new Request.Builder()
                .url(createUrlFromParams(httpUrl, params))
                .get()
                .build();

        Call call = client.newCall(request);
        try {
            Response response = call.execute();
            BufferedSource result = ((RealResponseBody) (response.body())).source();
            LogUtil.i("aaaa", "--getFileUploadUrl--result--" + result);
            String respStr = result.readUtf8();

//            Gson gson = new Gson();
//            OssUrlResp resp = gson.fromJson(respStr, OssUrlResp.class);
//            if (resp != null && "0".equals(resp.getStatus())) {
//                newUrl = resp.getData();
//                LogUtil.i("aaaa", "--newUrl--" + newUrl);
//            }
        }
//        catch (JsonSyntaxException e) {
//            e.printStackTrace();
//        }
        catch (Exception e) {
            e.printStackTrace();
        }
        return newUrl;
    }


    /**
     * 响应体进度回调接口，比如用于文件下载中
     */
    public interface ProgressResponseListener {
        void onResponseProgress(long bytesRead, long contentLength, boolean done);
    }

    /**
     * 包装的响体，处理进度
     */
    public class ProgressResponseBody extends ResponseBody {
        //实际的待包装响应体
        private final ResponseBody responseBody;
        //进度回调接口
        private final ProgressResponseListener progressListener;
        //包装完成的BufferedSource
        private BufferedSource bufferedSource;

        /**
         * 构造函数，赋值
         *
         * @param responseBody     待包装的响应体
         * @param progressListener 回调接口
         */
        public ProgressResponseBody(ResponseBody responseBody, ProgressResponseListener progressListener) {
            this.responseBody = responseBody;
            this.progressListener = progressListener;
        }


        /**
         * 重写调用实际的响应体的contentType
         *
         * @return MediaType
         */
        @Override
        public MediaType contentType() {
            return responseBody.contentType();
        }

        /**
         * 重写调用实际的响应体的contentLength
         */
        @Override
        public long contentLength() {
            return responseBody.contentLength();
        }

        /**
         * 重写进行包装source
         *
         * @return BufferedSource
         * @throws IOException 异常
         */
        @Override
        public BufferedSource source() {
            if (bufferedSource == null) {
                //包装
                bufferedSource = Okio.buffer(source(responseBody.source()));
            }
            return bufferedSource;
        }

        /**
         * 读取，回调进度接口
         *
         * @param source Source
         * @return Source
         */
        private Source source(Source source) {

            return new ForwardingSource(source) {
                //当前读取字节数
                long totalBytesRead = 0L;

                @Override
                public long read(Buffer sink, long byteCount) throws IOException {
                    long bytesRead = super.read(sink, byteCount);
                    //增加当前读取的字节数，如果读取完成了bytesRead会返回-1
                    totalBytesRead += bytesRead != -1 ? bytesRead : 0;
                    //回调，如果contentLength()不知道长度，会返回-1
                    progressListener.onResponseProgress(totalBytesRead, responseBody.contentLength(), bytesRead == -1);
                    return bytesRead;
                }
            };
        }
    }

    //get
    public void uploadPics(String httpUrl, RequestBody requestBody, Callback callback) {
        try {
            Request request = new Request.Builder()
                    .url(httpUrl)//完整的api路径
                    .addHeader("Content-Type", "image/jpeg")
                    .post(requestBody)
                    .build();
            Call call = client.newCall(request);
            call.enqueue(callback);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
